import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;

public class customer {
	
	String id, password;
	String url = "jdbc:mysql://localhost:3306/bank";
	String dbid = "root";
	String pw = "1234";
	
	public customer(String id, String pw) {
		
		int balance, menu;
		this.id = id;
		this.password = pw;
		
		do {
			printMenu();
			menu = selectMenu();
			
			switch(menu) {
			case 1:
				deposit();
				balance = getBalance();
				System.out.println("현재 잔액 : " + balance + "원");
				System.out.println();
				break;
			case 2:
				withdraw();
				balance = getBalance();
				System.out.println("현재 잔액 : " + balance + "원");
				System.out.println();
				break;
			case 3:
				transfer();
				System.out.println();
				break;
			case 4:
				printCustomerInfo();
				System.out.println();
				break;
			case 5:
				changeCustomerInfo();
				System.out.println();
				break;
			case 6:
				break;
			}
		}while(menu!=6);
	}
	
	private void printMenu() {
		System.out.println("1.입금\n2.출금\n3.이체\n4.내 정보 보기\n5.내 정보 수정\n6.로그아웃");
	}
	
	private int selectMenu() {
		int menuNum;
		Scanner scan = new Scanner(System.in);
		
		while(true) {
			System.out.print("원하시는 메뉴를 선택하세요 >> ");
			menuNum = scan.nextInt();
		
			if(menuNum < 1 || menuNum > 6)
				System.out.println("잘못 입력된 값입니다. 다시 입력 해 주세요.");
			else break;
		}
		return menuNum;
	}
	
	private void deposit() {
		int money, balance;
		
		System.out.print("입금하실 금액을 입력해 주세요 >> ");
		money = getMoney();
		balance = getBalance();
		
		// db에서 balance 증가
		setBalanceInDB(balance + money);
	}
	
	private void setBalanceInDB(int balance) {		
		try{
			Class.forName("com.mysql.jdbc.Driver");
		}catch(ClassNotFoundException e){
			System.out.println("드라이버 연결 실패 : " + e.toString());
		}
	
		try{
			Connection conn = DriverManager.getConnection(url, dbid, pw);
			PreparedStatement pre = conn.prepareStatement("UPDATE customer SET balance = ? WHERE id = ?");
			pre.setInt(1, balance);
			pre.setString(2, id);
			pre.executeUpdate();
			pre.close();
			conn.close();
		}catch(SQLException e){
			System.out.println("DB연결 및 작업처리 실패 : " + e.toString());
		}
	}
	
	private void setBalanceInDB(String id, int balance) {		
		try{
			Class.forName("com.mysql.jdbc.Driver");
		}catch(ClassNotFoundException e){
			System.out.println("드라이버 연결 실패 : " + e.toString());
		}
	
		try{
			Connection conn = DriverManager.getConnection(url, dbid, pw);
			PreparedStatement pre = conn.prepareStatement("UPDATE customer SET balance = ? WHERE id = ?");
			pre.setInt(1, balance);
			pre.setString(2, id);
			pre.executeUpdate();
			pre.close();
			conn.close();
		}catch(SQLException e){
			System.out.println("DB연결 및 작업처리 실패 : " + e.toString());
		}
	}
	
	private int getMoney() {
		int money;
		Scanner scan = new Scanner(System.in);
		
		while(true) {
			money = scan.nextInt();
			
			if(money < 1)
				System.out.println("1원 이상의 금액을 입력 해 주세요.");
			else break;
		}
		return money;
	}
	
	private int getBalance() {
		int balance = 0;
		
		//db에서 balance값 가져옴
		try{
			Class.forName("com.mysql.jdbc.Driver");
		}catch(ClassNotFoundException e){
			System.out.println("드라이버 연결 실패 : " + e.toString());
		}
	
		try{
			Connection conn = DriverManager.getConnection(url, dbid, pw);
			PreparedStatement pstmt = conn.prepareStatement("SELECT balance FROM customer WHERE id = ?");
			pstmt.setString(1, id);
			ResultSet rs = pstmt.executeQuery();
			rs.next();
			balance = rs.getInt(1);
		}catch(SQLException e){
			System.out.println("DB연결 및 작업처리 실패 : " + e.toString());
		}
		return balance;
	}
	
	private int getBalance(String id) {
		int balance = 0;
		
		//db에서 balance값 가져옴
		try{
			Class.forName("com.mysql.jdbc.Driver");
		}catch(ClassNotFoundException e){
			System.out.println("드라이버 연결 실패 : " + e.toString());
		}
	
		try{
			Connection conn = DriverManager.getConnection(url, dbid, pw);
			PreparedStatement pstmt = conn.prepareStatement("SELECT balance FROM customer WHERE id = ?");
			pstmt.setString(1, id);
			ResultSet rs = pstmt.executeQuery();
			rs.next();
			balance = rs.getInt(1);
		}catch(SQLException e){
			System.out.println("DB연결 및 작업처리 실패 : " + e.toString());
		}
		return balance;
	}
	
	private void withdraw() {
		int money, balance;
		
		balance = getBalance();
		
		if(balance==0)
			System.out.println("잔액이 0원 입니다.");
		else { 
			System.out.print("출금하실 금액을 입력하세요 >> ");
			money = getMoney();
			balance = getBalance();
			
			while(money > balance) {
				System.out.println("잔액보다 많은 금액을 입력했습니다.");
				System.out.print("출금하실 금액을 입력하세요 >> ");
				money = getMoney();
			}
			
			//db에서 money값만큼 balance에서 빼기
			setBalanceInDB(balance - money);			
			
			System.out.println(money + "원이 출금되었습니다.");
		}
	}
	
	private void transfer() {
		int money, balance, receiverBalance;
		String receiverId, receiverName;
		String accountNumber, yesOrNo;
		Scanner scan = new Scanner(System.in);
		
		System.out.print("이체하실 계좌번호를 입력하세요 >> ");
		accountNumber = getAccountNumber();
		
		if(accountNumber!=null) {
			receiverId = getIdOf(accountNumber);
			receiverName = getName(receiverId);
			System.out.println("입력하신 계좌의 예금주는 '" + receiverName + "'님 입니다.\n");
			
			balance = getBalance();
			
			if(balance == 0)
				System.out.println("잔액이 0원 입니다.");
			else {
				System.out.print("이체하실 금액을 입력하세요 >> ");
				money = getMoney();
				
				while(money > balance) {
					System.out.println("잔액보다 많은 금액을 입력했습니다.");
					System.out.print("이체하실 금액을 입력하세요 >> ");
					money = getMoney();
				}
				
				do {
					System.out.print("정말로 보내시겠습니까?(Yes/No) >> ");
					yesOrNo = scan.nextLine();
					
					if(!yesOrNo.toLowerCase().equals("yes") && !yesOrNo.toLowerCase().equals("no"))
						System.out.println("Yes 또는 No 로 입력해주세요.");
				}while(!yesOrNo.toLowerCase().equals("yes") && !yesOrNo.toLowerCase().equals("no"));
				
				if(yesOrNo.toLowerCase().equals("yes")) {
					//db값 수정
					setBalanceInDB(balance-money);
					receiverBalance = getBalance(receiverId);
					setBalanceInDB(receiverId, receiverBalance+money);
			
					System.out.println("받는 사람 계좌번호 : " + accountNumber);
					System.out.println("받는 사람 이름 : "+ receiverName);
					System.out.println("이체 금액 : " + money);
					System.out.println("이체가 성공적으로 이루어졌습니다.");
					balance = getBalance();
					System.out.println("현재 잔액 : " + balance + "원");
				}
				else {
					System.out.println("이체가 취소되었습니다.");
				}
			}
		}
		else {
			System.out.println("이체가 취소되었습니다.");
		}
	}
	
	private String getAccountNumber() {
		Scanner scan = new Scanner(System.in);
		String accountNumber;
		
		accountNumber = scan.nextLine();
		if(!existAccountNumber(accountNumber)){
			System.out.println("입력한 account number가 존재하지 않습니다.");
			return null;
		}
		return accountNumber;
	}
	
	private String getIdOf(String accountNumber) {
		String id = null;
		
		try{
			Class.forName("com.mysql.jdbc.Driver");
		}catch(ClassNotFoundException e){
			System.out.println("드라이버 연결 실패 : " + e.toString());
		}
	
		try{
			Connection conn = DriverManager.getConnection(url, dbid, pw);
			PreparedStatement pstmt = conn.prepareStatement("SELECT id FROM customer WHERE account_num = ?");
			pstmt.setString(1, accountNumber);
			ResultSet rs = pstmt.executeQuery();
			rs.next();
			id = rs.getString(1);
		}catch(SQLException e){
			System.out.println("DB연결 및 작업처리 실패 : " + e.toString());
		}
		return id;
	}

	private String getName(String id) {
		String name = null;
		
		try{
			Class.forName("com.mysql.jdbc.Driver");
		}catch(ClassNotFoundException e){
			System.out.println("드라이버 연결 실패 : " + e.toString());
		}
	
		try{
			Connection conn = DriverManager.getConnection(url, dbid, pw);
			PreparedStatement pstmt = conn.prepareStatement("SELECT name FROM customer WHERE id = ?");
			pstmt.setString(1, id);
			ResultSet rs = pstmt.executeQuery();
			rs.next();
			name = rs.getString(1);
		}catch(SQLException e){
			System.out.println("DB연결 및 작업처리 실패 : " + e.toString());
		}	
		return name;
	}
	
	private boolean existAccountNumber(String accountNumber) {
		//db에서 account number check
		//존재하면 true, 존재하지 않으면 false;
		try{
			Class.forName("com.mysql.jdbc.Driver");
		}catch(ClassNotFoundException e){
			System.out.println("드라이버 연결 실패 : " + e.toString());
		}
	
		try{
			Connection conn = DriverManager.getConnection(url, dbid, pw);
			Statement st = conn.createStatement();
			ResultSet rs = st.executeQuery("SELECT account_num FROM customer");
			while(rs.next()) {
				if(accountNumber.equals(rs.getString(1))) {
					st.close();
					conn.close();
					return true;
				}
			}
			st.close();
			conn.close();
		}catch(SQLException e){
			System.out.println("DB연결 및 작업처리 실패 : " + e.toString());
		}
		return false;
	}
	
	private void printCustomerInfo() {
		String name = null, registration_num = null, address = null, account_num = null;
		int balance = 0;
		
		//db에서 정보 가져와서 출력
		try{
			Class.forName("com.mysql.jdbc.Driver");
		}catch(ClassNotFoundException e){
			System.out.println("드라이버 연결 실패 : " + e.toString());
		}
	
		try{
			Connection conn = DriverManager.getConnection(url, dbid, pw);
			PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM customer WHERE id = ?");
			pstmt.setString(1, id);
			ResultSet rs = pstmt.executeQuery();
			rs.next();
			name = rs.getString(3);
			account_num = rs.getString(4);
			balance = rs.getInt(5);
			address = rs.getString(6);
			registration_num = rs.getString(7);
		}catch(SQLException e){
			System.out.println("DB연결 및 작업처리 실패 : " + e.toString());
		}
		
		System.out.println("ID : " + id);
		System.out.println("password : " + password);
		System.out.println("name : " + name);
		System.out.println("account number : " + account_num);
		System.out.println("registration number : " + registration_num);
		System.out.println("address : " + address);
		System.out.println("balance : " + balance);
		
		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		try {
			in.readLine();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private void changeCustomerInfo(){
		
		Scanner scan = new Scanner(System.in);
		int submenu;
		
		do {
			System.out.println("1.password 수정");
			System.out.println("2.address 수정");
			System.out.println("3.취소");
			do {
				System.out.print("원하시는 메뉴를 선택하세요 >> ");
				submenu = scan.nextInt();
				if(submenu < 1 || submenu > 3)
					System.out.println("잘못 입력된 값입니다. 다시 입력 해 주세요.");
			}while(submenu < 1 || submenu > 3);
			
			switch(submenu) {
			case 1:
				changePassword();
				break;
			case 2:
				changeAddress();
				break;
			}
		}while(submenu!=3);
	}
	
	private void changePassword() {
		Scanner scan = new Scanner(System.in);
		String oldPass, newPass, reNewPass;
		
		while(true) {
			System.out.print("현재 비밀번호를 입력하세요 >> ");
			oldPass = scan.nextLine();
			
			if(oldPass.equals(password))
				break;
			else
				System.out.println("입력한 비밀번호가 틀립니다. 다시 입력해 주세요.");
		} 
		
		while(true) {
			System.out.print("새로운 비밀번호를 입력하세요 >> ");
			newPass = scan.nextLine();
			System.out.print("한 번 더 입력하세요 >> ");
			reNewPass = scan.nextLine();
			
			if(newPass.equals(reNewPass))
				break;
			else
				System.out.println("새로운 비밀번호 두 값이 서로 다릅니다. 다시 입력해주세요.");
		}	
		setPasswordInDB(newPass);
		password = newPass;
		System.out.println("비밀번호가 성공적으로 바뀌었습니다.");
	}
	
	private void setPasswordInDB(String newPass) {
		try{
			Class.forName("com.mysql.jdbc.Driver");
		}catch(ClassNotFoundException e){
			System.out.println("드라이버 연결 실패 : " + e.toString());
		}
	
		try{
			Connection conn = DriverManager.getConnection(url, dbid, pw);
			PreparedStatement pre = conn.prepareStatement("UPDATE customer SET pw = ? WHERE id = ?");
			pre.setString(1, newPass);
			pre.setString(2, id);
			pre.executeUpdate();
			pre.close();
			conn.close();
		}catch(SQLException e){
			System.out.println("DB연결 및 작업처리 실패 : " + e.toString());
		}
	}
	
	private void changeAddress() {
		Scanner scan = new Scanner(System.in);
		String newAddress, address = getAddress();
		
		System.out.println("현재 주소 : " + address);
		System.out.print("새로운 주소를 입력하세요 >> ");
		newAddress = scan.nextLine();
		
		//db값 변경
		setAddressInDB(newAddress);
		
		System.out.println("주소가 성공적으로 바뀌었습니다.");
	}
	
	private String getAddress() {
		String address = null;
		
		//db에서 주소 가져오기
		try{
			Class.forName("com.mysql.jdbc.Driver");
		}catch(ClassNotFoundException e){
			System.out.println("드라이버 연결 실패 : " + e.toString());
		}
	
		try{
			Connection conn = DriverManager.getConnection(url, dbid, pw);
			PreparedStatement pstmt = conn.prepareStatement("SELECT address FROM customer WHERE id = ?");
			pstmt.setString(1, id);
			ResultSet rs = pstmt.executeQuery();
			rs.next();
			address = rs.getString(1);
		}catch(SQLException e){
			System.out.println("DB연결 및 작업처리 실패 : " + e.toString());
		}
		
		return address;
	}
	
	private void setAddressInDB(String newAddress) {
		try{
			Class.forName("com.mysql.jdbc.Driver");
		}catch(ClassNotFoundException e){
			System.out.println("드라이버 연결 실패 : " + e.toString());
		}
	
		try{
			Connection conn = DriverManager.getConnection(url, dbid, pw);
			PreparedStatement pre = conn.prepareStatement("UPDATE customer SET address = ? WHERE id = ?");
			pre.setString(1, newAddress);
			pre.setString(2, id);
			pre.executeUpdate();
			pre.close();
			conn.close();
		}catch(SQLException e){
			System.out.println("DB연결 및 작업처리 실패 : " + e.toString());
		}
	}
}